// 单件商品数据
class UIGoods {
    // 构造函数
    constructor(g) {
        this.data = g;
        this.choose = 0
    }
    // 单个总价
    getTotalPrice() {
        return this.data.price * this.choose
    }
    // 是否选中
    isChoose() {
        return this.choose > 0
    }
    // 单个商品数量增加
    increase() {
        this.choose++;
    }
    // 单个商品数量减少
    decrease() {
        // 如果单个商品数量为0就不再减了
        if (this.choose === 0) return;
        this.choose--;
    }
}

// 整个界面的数据
class UIData {
    constructor() {
        // 新数组数据并且包含单个商品选中
        this.UIGoods = goods.map(good => new UIGoods(good));
        this.deliveryThreshold = 30; // 配送标准，hard code 硬代码
        this.deliveryPrice = 5; // 基础配送费，hard code 硬代码
    }
    // 因为避免操作最底层对象，要直接操作当前对象，所以会用当前对象再去调一次底层对象的一些方法
    // 计算所有商品加起来的总价
    getTotalPrice() {
        return this.UIGoods.reduce((acc, cur) => acc + cur.getTotalPrice(), 0)
    }
    // 是否选中
    isChoose(index) {
        return this.UIGoods[index].isChoose()
    }
    // 增加某件商品的选中数量
    increase(index) {
        this.UIGoods[index].increase()
    }
    // 减少某件商品的选中数量
    decrease(index) {
        this.UIGoods[index].decrease()
    }
    // 得到总共的选择数量
    getTotalChooseNumber() {
        return this.UIGoods.reduce((acc, cur) => acc + cur.choose, 0)
    }
    // 购物车中是否有商品
    hasGoodsInCart() {
        return this.getTotalChooseNumber() > 0
    }
    // 是否跨越配送标准
    isCrossDeliveryThreshold() {
        return this.getTotalPrice() >= this.deliveryThreshold
    }
}

// 界面
class UI {
    constructor() {
        // 整个页面的数据及数据逻辑
        this.uiData = new UIData();
        // 为了防止变量污染，尽量用对象收纳
        this.doms = {
            // 商品容器
            goodsContainer: document.querySelector('.goods-list'), // 所有商品
            totalPrice: document.querySelector('.footer-car-total'), // 总价
            deliveryPrice: document.querySelector('.footer-car-tip'), // 配送费
            deliveryThreshold: document.querySelector('.footer-pay span'), // 配送标准
            footerPay: document.querySelector('.footer-pay'), // 去支付
            car: document.querySelector('.footer-car'), // 购物车图标
            badge: document.querySelector('.footer-car-badge'), // 商品总数
        }
        // 获取购物车位置
        const cart = this.doms.car.getBoundingClientRect()
        // 跳跃的目标位置
        this.jumpTarget = {
            x: cart.left + cart.width / 2,
            y: cart.top + cart.height / 5,
        }
        this.createHtml()
        this.updateFooter()
        this.listenEvent()
    }
    // 所有事件监听
    createHtml() {
        // 创建html字符串，生成商品列表，使用map方法获取每项的html字符串，然后用reduce拼接起来
        this.doms.goodsContainer.innerHTML = this.uiData.UIGoods.map((v, i) => `<div class="goods-item">
            <img src="${v.data.pic}" alt="" class="goods-pic" />
            <div class="goods-info">
            <h2 class="goods-title">${v.data.title}</h2>
            <p class="goods-desc">
                ${v.data.desc}
            </p>
            <p class="goods-sell">
                <span>月售 ${v.data.sellNumber}</span>
                <span>好评率${v.data.favorRate}%</span>
            </p>
            <div class="goods-confirm">
                <p class="goods-price">
                <span class="goods-price-unit">￥</span>
                <span>${v.data.price}</span>
                </p>
                <div class="goods-btns">
                <i data-index="${i}" class="iconfont i-jianhao"></i>
                <span>${v.choose}</span>
                <i data-index="${i}" class="iconfont i-jiajianzujianjiahao"></i>
                </div>
            </div>
            </div>
        </div>`).reduce((acc, cur) => acc + cur, '')
    }
    // 增加某件商品的选中数量
    increase(index) {
        this.uiData.increase(index)
        this.updateGoodsItem(index)
        this.updateFooter()
        this.jump(index)
    }
    // 减少某件商品的选中数量
    decrease(index) {
        this.uiData.decrease(index)
        this.updateGoodsItem(index)
        this.updateFooter()
    }
    // 更新某个元素的显示状态
    updateGoodsItem(index) {
        // 获取当前元素
        const goodsDom = this.doms.goodsContainer.children[index]
        if (this.uiData.isChoose(index)) {
            // 如果当前元素被选中就加上active类
            goodsDom.classList.add('active')
        } else {
            // 否则去掉active类
            goodsDom.classList.remove('active')
        }
        // 顺便改变选择个数
        goodsDom.querySelector('.goods-btns span').textContent = this.uiData.UIGoods[index].choose
    }
    // 更新页脚
    updateFooter() {
        // 获取总价
        const total = this.uiData.getTotalPrice()
        // 设置总价
        this.doms.totalPrice.textContent = total.toFixed(2);
        // 设置配送费
        this.doms.deliveryPrice.textContent = `配送费￥${this.uiData.deliveryPrice}`
        // 设置购物车中的数量
        this.doms.badge.textContent = this.uiData.getTotalChooseNumber()
        // 设置还差多少配送
        this.doms.deliveryThreshold.textContent = `还差￥${Math.trunc(this.uiData.deliveryThreshold - total)}元起送`
        // 配送标准
        if (this.uiData.isCrossDeliveryThreshold()) {
            this.doms.footerPay.classList.add('active')
        } else {
            this.doms.footerPay.classList.remove('active')
        }
        // 购物车
        if (total > 0) {
            this.doms.car.classList.add('active')
        } else {
            this.doms.car.classList.remove('active')
        }
    }
    // 购物车动画事件
    listenEvent() {
        this.doms.car.addEventListener('animationend', function () {
            // 这里的this指向元素，所以可以直接使用
            this.classList.remove('animate')
        })
    }
    // 购物车动画
    cartAnimate() {
        this.doms.car.classList.add('animate')
    }
    // 抛物线跳跃的元素
    jump(index) {
        // 找到商品对应加号
        const btnAdd = this.doms.goodsContainer.children[index].querySelector('.i-jiajianzujianjiahao')
        const rect = btnAdd.getBoundingClientRect()
        const start = { x: rect.left, y: rect.top, }; // 获取商品的位置
        // 创建跳跃的元素
        const div = document.createElement('div')
        div.className = 'add-to-car'
        const i = document.createElement('i')
        i.className = 'iconfont i-jiajianzujianjiahao'
        // 设置初始位置
        div.style.transform = `translateX(${start.x}px`
        i.style.transform = `translateY(${start.y}px`
        // 添加元素
        div.appendChild(i)
        document.body.appendChild(div)
        div.clientHeight // 强制渲染
        // 结束位置
        div.style.transform = `translateX(${this.jumpTarget.x}px)`
        i.style.transform = `translateY(${this.jumpTarget.y}px)`
        const that = this;
        // 监听过渡结束的事件（因为事件冒泡，事件仅触发一次）
        div.addEventListener('transitionend', function () {
            div.remove() // 避免元素过多
            that.cartAnimate() // 购物车动画
        }, { once: true })
    }
}

// 创建ui对象
const ui = new UI()
// 事件（使用事件委托的方式：事件冒泡，点击哪个元素，就打印哪个元素）
ui.doms.goodsContainer.addEventListener("click", function (e) {
    const { classList } = e.target
    const { index } = e.target.dataset
    if (classList.contains('i-jiajianzujianjiahao')) {
        // 加号事件
        ui.increase(+index)
    } else if (classList.contains('i-jianhao')) {
        // 减号事件
        ui.decrease(+index)
    }
})
